<template>
	<BasePopup
		v-model="show"
		:titleT="pageInfo.titleT"
		titleIcon="settings"
		:maskClosable="false"
		@close="onClose">
		<form class="account-verify px-[25px] md:px-[35px] pt-4 pb-10" @submit.prevent="onEnter">
			<input type="submit" class="hidden" />
			<div v-show="loadingPage" class="py-[58px]">
				<BaseLoadingCircle class="mx-auto" />
			</div>
			<div v-show="!loadingPage">
				<BaseTip class="mb-4" :text-t="pageInfo.tipT" />
				<BaseInput
					v-model="formValue.code"
					:name="FormFieldName.verifyCode"
					:labelT="pageInfo.labelT"
					:placeholder="tInput(pageInfo.placeholderT)"
					:errorT="formRule.code.result.textT"
					:is-danger="!formRule.code.result.valid"
					@blur="formRule.code.validator()"
					@focus="formReset('code')">
					<template #suffix>
						<BasePaste
							v-show="pageInfo?.verifyType === VerifyType['2fa']"
							@paste="(v: string) => (formValue.code = v)" />
						<BaseCodeEmail
							ref="emailCodeRef"
							v-show="pageInfo?.verifyType === VerifyType['email']"
							:email="pageInfo.email"
							:retry="!appear" />
						<BaseCodePhone
							ref="mobileCodeRef"
							v-show="pageInfo?.verifyType === VerifyType['mobile']"
							:phone-number="pageInfo.mobile"
							:area-code="pageInfo.internationalAreaCode"
							:retry="!appear" />
					</template>
				</BaseInput>
				<BaseButton
					class="mt-10"
					type="primary"
					:textT="confirmTextT"
					:loading="loadingButton"
					@click="onEnter" />
			</div>
		</form>
	</BasePopup>
</template>

<script setup lang="ts">
import { computed, nextTick, PropType, reactive, ref } from 'vue'
import { Enable2fa, Login, VerifyCodeType, VerifyType } from '@/api/account-type.ts'
import {
	BaseButton,
	BaseCodeEmail,
	BaseCodePhone,
	BaseInput,
	BaseLoadingCircle,
	BasePaste,
	BasePopup,
	BaseTip
} from '@/components/base'
import { FormFieldName } from '@/enums'
import { useProfileStore } from '@/store'
import { fmtEmail, fmtMobile, isCode, tInput } from '@/utils'
import { Action } from '@/types'
import { RuleType } from '@/components/base/input-rule/index.vue'

defineOptions({ name: 'AccountOperateVerify' })
const props = defineProps({
	// 是否在首次出现时请求验证码; false时表示前置接口已经请求过验证码了
	appear: {
		type: Boolean,
		default: true
	},
	// 从前置接口返回的验证码信息
	verifyInfo: {
		type: Object as PropType<Login['result'] | Enable2fa['result']>
	},
	confirmTextT: {
		type: [String, Array],
		default: 'action.confirm'
	},
	// 按下 confirm 按钮的回调, 如果返回true值 则关闭弹窗; 也可以通过ref调用close()方法
	onFinish: Function
})
const emits = defineEmits(['close', 'finish'])
const profileStore = useProfileStore()
const mobileCodeRef = ref<InstanceType<typeof BaseCodePhone>>()
const emailCodeRef = ref<InstanceType<typeof BaseCodeEmail>>()
const show = ref(false)
const loadingPage = ref(false)
const loadingButton = ref(false)
const formValue = reactive({ code: '' })
const formRule = reactive({
	code: {
		hasInput: false,
		result: <RuleType>{ valid: true },
		validator: (action?: Action) => {
			if (action === Action.reset) return (formRule.code.result = { valid: true })
			if (action === Action.input) formRule.code.hasInput = true
			if (action === Action.blur && !formRule.code.hasInput) return
			const value = formValue.code
			let msg = ''
			if (!isCode(value)) {
				msg = 'reset.step2Title'
			}
			formRule.code.result = { textT: msg, valid: !msg }
		}
	}
})
const pageInfo = computed(() => {
	const _info: any = props.verifyInfo || profileStore.userInfo
	type PageInfo = {
		verifyType: string
		titleT: string | any[]
		tipT: string | any[]
		labelT: string | any[]
		placeholderT: string | any[]
		email: string
		internationalAreaCode: string
		mobile: string
	}
	const page = {
		'2fa': {
			verifyType: VerifyType['2fa'],
			titleT: 'login.2faAuthentication',
			tipT: 'login.2faAuthenticationTip',
			labelT: 'login.2faCode',
			placeholderT: 'login.2faCode',
			email: '',
			internationalAreaCode: '',
			mobile: ''
		},
		email: {
			verifyType: VerifyType['email'],
			titleT: 'login.emailAuthentication',
			tipT: ['reset.step2Subtitle', [fmtEmail(_info?.email)]] as string | any[],
			labelT: 'email.code',
			placeholderT: 'email.code',
			email: _info?.email || '',
			internationalAreaCode: '',
			mobile: ''
		},
		mobile: {
			verifyType: VerifyType['mobile'],
			titleT: 'login.mobileAuthentication',
			tipT: [
				'reset.step2Subtitle',
				[fmtMobile(_info?.internationalAreaCode + ' ' + _info?.mobile)]
			] as any,
			labelT: 'account.mobileCode',
			placeholderT: 'account.mobileCode',
			email: '',
			internationalAreaCode: _info?.internationalAreaCode || '',
			mobile: _info?.mobile || ''
		}
	}
	// 根据login接口返回(邮箱|手机|2fa) 判断要展示的标题等信息
	let _pageInfo: PageInfo
	if (_info?.enable2fa) {
		_pageInfo = page['2fa']
	} else if (_info?.emailVerify || _info?.verifyCodeType === VerifyCodeType.email) {
		_pageInfo = page.email
	} else if (_info?.mobileVerify || _info?.verifyCodeType === VerifyCodeType.mobile) {
		_pageInfo = page.mobile
	} else {
		_pageInfo = page.email
	}
	return _pageInfo
})
const submitDisabled = computed(
	() => !formValue.code || Object.values(formRule).some(({ result: { valid } }) => !valid)
)

const formReset = (field: keyof typeof formRule, withValue: boolean = false) => {
	if (withValue && formValue[field]) formValue[field] = ''
	nextTick(() => {
		formRule[field]?.hasInput && (formRule[field].hasInput = false)
		formRule[field]?.validator?.(Action.reset)
	})
}
const openVerify = async () => {
	show.value = true
	loadingPage.value = true
	await nextTick(async () => {
		if (props.appear) {
			switch (pageInfo.value.verifyType) {
				case VerifyType['2fa']:
					break
				case VerifyType.email:
					await emailCodeRef.value?.onClick()
					break
				case VerifyType.mobile:
					await mobileCodeRef.value?.onClick()
					break
			}
		}
		loadingPage.value = false
	})
}
const handleClose = () => {
	show.value = false
	onClose()
}
const onClose = () => {
	formReset('code', true)
	emits('close')
}
const onSubmit = async () => {
	loadingButton.value = true
	const params = {
		verifyType: pageInfo.value.verifyType,
		verifyCode: formValue.code
	}
	if (typeof props.onFinish === 'function') {
		const res = await props.onFinish(params)
		if (res) show.value = false
	} else {
		emits('finish', params)
		show.value = false
	}
	loadingButton.value = false
}
const onEnter = async () => {
	if (loadingPage.value) return
	Object.values(formRule).forEach(({ validator }) => validator(Action.submit))
	await nextTick(() => {
		if (submitDisabled.value) return
		onSubmit()
	})
}

defineExpose({ openVerify, close: handleClose })
</script>

<style scoped></style>
